package net.sansi.v3correctserver.entity.image;

import cn.hutool.core.io.FileUtil;
import net.sansi.v3correctserver.entity.IntPoint;
import net.sansi.v3correctserver.entity.color.CIEChroma;
import net.sansi.v3correctserver.entity.color.PhotoColor;
import net.sansi.v3correctserver.exception.ServiceException;

import java.awt.*;
import java.nio.file.Path;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * Created by Fang
 * create time : 2024/11/1
 * IDE : IntelliJ IDEA
 * <p>
 * 识别用图片对象
 */

public interface RecImage {

    /**
     * 创建识别用图片对象
     *
     * @param path 图片路径
     * @return 识别用图片对象
     */
    static RecImage load(Path path, RecImage blackPath) {
        FutureTask<RecImageBase> future = new FutureTask<>(() -> {
            if (!path.toFile().exists()) {
                throw new ServiceException("相片文件不存在 {}", path.toFile().getAbsoluteFile());
            }
            String suffix = FileUtil.getSuffix(path.toFile());
            if ("jpg,jpeg,png,bmp".contains(suffix.toLowerCase())) {
                return new RecCmmImage(path, blackPath);
            }
            if ("cr2,cr3".contains(suffix.toLowerCase())) {
                return new RecRawImage(path, blackPath);
            }
            throw new ServiceException("相片类型不支持 {}", path.toFile().getAbsoluteFile());
        });
        Thread task = new Thread(future);
        task.start();
        try {
            return future.get(20, TimeUnit.SECONDS);
        } catch (ExecutionException e) {
            throw new ServiceException("执行异常 {}", e.getMessage());
        } catch (InterruptedException e) {
            throw new ServiceException("异常中断 {}", e.getMessage());
        } catch (TimeoutException e) {
            throw new ServiceException("超时 {}", e.getMessage());
        }
    }

    static RecImage load(Path path) {
        return load(path, null);
    }

    /**
     * 获取相片位置
     * 如果是手动生成的相片，getPath 为空
     *
     * @return 绝对路径
     */
    Path getPath();

    /**
     * 设置图片路径
     */
    void setPath(Path path);


    /**
     * 获取图片宽度
     *
     * @return 图片宽度
     */
    int getWidth();

    /**
     * 获取图片高度
     *
     * @return 图片高度
     */
    int getHeight();

    /**
     * 获取指定坐标的颜色（标准 rgb 0-255）
     *
     * @param x x 坐标
     * @param y y 坐标
     * @return 0-255 rgb 坐标
     */
    Color getColor(int x, int y);

    /**
     * 获取指定坐标的颜色（没有大小限制，可以是某个区域的 rgb 之和）
     *
     * @param x x 坐标
     * @param y y 坐标
     * @return 无上限的 rgb 坐标
     */
    PhotoColor getPhotoColor(int x, int y);

    /**
     * 获取 cie 颜色
     *
     * @param x x 坐标
     * @param y y 坐标
     * @return cie 坐标
     */
    CIEChroma getCIEChroma(int x, int y);

    /**
     * 读取某个像素的亮度
     *
     * @param x x
     * @param y y 坐标
     * @return 亮度
     */
    double getBrightness(int x, int y);

    /**
     * 保存图片
     *
     * @param path 保存路径
     */
    void save(Path path);

    /**
     * 设置颜色
     *
     * @param x     x坐标
     * @param y     y坐标
     * @param color 填充颜色
     */
    void setColor(int x, int y, PhotoColor color);

    /**
     * 设置颜色
     *
     * @param point 像素点
     * @param color 填充颜色
     */
    void setColor(IntPoint point, PhotoColor color);

    /**
     * 在图片上画一条线
     *
     * @param p1    左上角
     * @param p2    右下角
     * @param color 颜色
     */
    void drawLine(IntPoint p1, IntPoint p2, PhotoColor color);

    /**
     * 在图片上画一个矩形
     *
     * @param ltPoint 左上角
     * @param rbPoint 右下角
     * @param color   颜色
     */
    void drawRect(IntPoint ltPoint, IntPoint rbPoint, PhotoColor color);

    /**
     * 在图片上填充一个矩形
     *
     * @param ltPoint 左上角
     * @param rbPoint 右下角
     * @param color   颜色
     */
    void fillRect(IntPoint ltPoint, IntPoint rbPoint, PhotoColor color);

    /**
     * 在图片上写文字
     *
     * @param startPoint 起始点
     * @param text       文字
     * @param color      颜色
     */
    void writeText(IntPoint startPoint, String text, PhotoColor color);

    /**
     * 设置背景颜色
     *
     * @param color 颜色
     */
    void setBackgroundColor(PhotoColor color);
}
